package com.my.kindlesend.service;

import cn.hutool.extra.spring.SpringUtil;
import com.my.kindlesend.dao.FileInfoDao;
import com.my.kindlesend.dao.UploadFileDao;
import com.my.kindlesend.dao.UserInfoDao;
import com.my.kindlesend.entity.FileInfo;
import com.my.kindlesend.entity.UploadFile;
import com.my.kindlesend.entity.UserInfo;
import com.my.kindlesend.enums.FileSendStatusEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 文件发送任务服务类
 * 定时查询未发送的文件并通过线程池异步发送到用户的kindle邮箱
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class FileSendTaskService {

    private final UploadFileDao uploadFileDao;
    private final UserInfoDao userInfoDao;
    private final FileInfoDao fileInfoDao;
    private final MailService mailService;
    private final ThreadPoolExecutor fileSendThreadPool;

    @Value("${file.upload.path}")
    private String uploadPath;

    /**
     * 定时任务：每5秒检查一次未发送的文件
     */
    @Scheduled(cron = "*/5 * * * * ?")
    public void checkAndSendFiles() {
        log.info("开始检查未发送的文件...");
        
        // 查询所有未发送的文件
        List<UploadFile> unsentFiles = uploadFileDao.findByStatus(FileSendStatusEnum.NOT_SENT.getCode());
        log.info("发现{}个未发送的文件", unsentFiles.size());
        
        // 提交每个文件到线程池进行处理
        for (UploadFile file : unsentFiles) {
            fileSendThreadPool.submit(() -> SpringUtil.getBean(FileSendTaskService.class).processFile(file));
        }
    }

    /**
     * 处理单个文件的发送逻辑
     * @param uploadFile 待发送的文件信息
     */
    @Transactional
    public void processFile(UploadFile uploadFile) {
        try {
            log.info("开始处理文件: {}, ID: {}", uploadFile.getFileName(), uploadFile.getId());
            
            // 先将文件状态设置为发送中，防止重复处理
            uploadFile.setStatus(FileSendStatusEnum.SENDING.getCode());
            uploadFile.setUpdateTime(LocalDateTime.now());
            uploadFile = uploadFileDao.save(uploadFile);
            
            // 查询用户信息
            Optional<UserInfo> userOptional = userInfoDao.findById(uploadFile.getUserInfoId());
            if (userOptional.isEmpty()) {
                String errorMsg = "未找到用户信息，用户ID: " + uploadFile.getUserInfoId();
                log.error(errorMsg);
                updateFileStatus(uploadFile, FileSendStatusEnum.SENT_FAILED.getCode(), errorMsg);
                return;
            }
            
            UserInfo userInfo = userOptional.get();
            if (userInfo.getKindleEmail() == null || userInfo.getKindleEmail().trim().isEmpty()) {
                String errorMsg = "用户未设置Kindle邮箱，用户ID: " + userInfo.getId();
                log.error(errorMsg);
                updateFileStatus(uploadFile, FileSendStatusEnum.SENT_FAILED.getCode(), errorMsg);
                return;
            }
            
            // 查询文件信息
            Optional<FileInfo> fileInfoOptional = fileInfoDao.findById(uploadFile.getFileInfoId());
            if (fileInfoOptional.isEmpty()) {
                String errorMsg = "未找到文件信息，文件ID: " + uploadFile.getFileInfoId();
                log.error(errorMsg);
                updateFileStatus(uploadFile, FileSendStatusEnum.SENT_FAILED.getCode(), errorMsg);
                return;
            }
            
            FileInfo fileInfo = fileInfoOptional.get();
            // 构建文件路径
            String filePath = Path.of(uploadPath, fileInfo.getFileName()).toString();
            File file = new File(filePath);
            
            if (!file.exists() || !file.isFile()) {
                String errorMsg = "文件不存在: " + filePath;
                log.error(errorMsg);
                updateFileStatus(uploadFile, FileSendStatusEnum.SENT_FAILED.getCode(), errorMsg);
                return;
            }
            
            // 发送邮件到用户的Kindle邮箱
            String subject = "Kindle文件发送：" + uploadFile.getFileName();
            String content = "亲爱的用户，您的文件已经发送到您的Kindle设备，请注意查收。";
            boolean sendResult = mailService.sendMailWithAttachment(userInfo.getKindleEmail(), subject, content, file);
            
            if (sendResult) {
                // 发送成功，更新状态
                updateFileStatus(uploadFile, FileSendStatusEnum.SENT_SUCCESS.getCode(), "发送成功");
                log.info("文件发送成功: {}, 收件人: {}", uploadFile.getFileName(), userInfo.getKindleEmail());
            } else {
                // 发送失败，更新状态和错误信息
                String errorMsg = "邮件发送失败，可能是邮件服务器问题或邮箱地址无效";
                updateFileStatus(uploadFile, FileSendStatusEnum.SENT_FAILED.getCode(), errorMsg);
                log.error("文件发送失败: {}", uploadFile.getFileName());
            }
        } catch (Exception e) {
            // 捕获所有异常，确保任务不会中断
            String errorMsg = "处理文件时发生异常: " + e.getMessage();
            log.error(errorMsg, e);
            try {
                // 尝试更新文件状态为失败
                updateFileStatus(uploadFile, FileSendStatusEnum.SENT_FAILED.getCode(), errorMsg);
            } catch (Exception ex) {
                log.error("更新文件状态失败", ex);
            }
        }
    }

    /**
     * 更新文件状态
     * @param uploadFile 文件信息
     * @param status 新状态
     * @param result 结果描述
     */
    @Transactional
    public void updateFileStatus(UploadFile uploadFile, Integer status, String result) {
        uploadFile.setStatus(status);
        uploadFile.setResult(result);
        uploadFile.setUpdateTime(LocalDateTime.now());
        uploadFileDao.save(uploadFile);
    }
}